package org.objectsearch.web.tools;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.ParseException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

import com.alianzamedica.businessobject.BusinessObject;

/**
 * @author Carlos
 * 
 */
public class ObjectXmlSerializer {

	private boolean iterative = false;

	private Document document;

	ObjectXmlConfigurationEnviroment settings;

	/**
	 * @param document
	 */
	public ObjectXmlSerializer(Document document) {
		this.document = document;
		settings = ObjectXmlConfigurationEnviroment.getInstance();
	}

	/**
	 * pregunta si es iterativo.
	 * 
	 * @return iterativo.
	 */
	public boolean isIterative() {
		return iterative;
	}

	/**
	 * setea el valor de iterativo.
	 * 
	 * @param iterative
	 */
	public void setIterative(boolean iterative) {
		this.iterative = iterative;
	}

	/**
	 * cambia un objeto a elemento.
	 * 
	 * @param object
	 *            objeto a cambiar.
	 * @return objeto.
	 */
	@SuppressWarnings("unchecked")
	public Element object2Element(Object object) {
		Class _class = object.getClass();
		String simpleName = _class.getSimpleName();
		Element element = document.createElement(simpleName);
		Field[] fields = _class.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			try {
				int modifier = field.getModifiers();
				if (!Modifier.isStatic(modifier)) {
					field.setAccessible(true);
					Object result = field.get(object);
					Element el = document.createElement(field.getName());
					String fieldType = field.getType().getName();
					if (result != null) {
						if ("java.util.Date".equals(fieldType)) {
							String sDate = FormatDateTool
									.formatDate((Date) result);
							if (sDate != null) {
								Text text = document.createTextNode(sDate);
								el.appendChild(text);
							}
						} else {
							Text text = document.createTextNode(result
									.toString());
							el.appendChild(text);
						}
					}
					element.appendChild(el);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return element;
	}

	/**
	 * @param object
	 * @param props
	 * @throws ParseException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	@SuppressWarnings("unchecked")
	public void assignProperties2Element(Object object, Properties props)
			throws ParseException, IllegalArgumentException,
			IllegalAccessException {
		Class _class = object.getClass();
		Hashtable hash = new Hashtable();
		Field[] fields = _class.getDeclaredFields();
		Field[] superClassFields = this.getFieldsFromParentClass(object);
		Field[] tempFields = new Field[fields.length + superClassFields.length];
		System.arraycopy(fields, 0, tempFields, 0, fields.length);
		System.arraycopy(superClassFields, 0, tempFields, fields.length,
				superClassFields.length);
		fields = tempFields;
		/*
		 * int iField = 0; while( iField < fields.length ){ tempFields[iField] =
		 * fields[iField]; iField++; } while( iField < ( fields.length +
		 * superClassFields.length ) ){ tempFields[iField] =
		 * superClassFields[iField]; iField++; } fields = tempFields;
		 */
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			String key = field.getName();
			hash.put(key, field);
		}
		Enumeration keys = props.keys();
		while (keys.hasMoreElements()) {
			String key = (String) keys.nextElement();
			String sVal = props.getProperty(key);
			if (key.equalsIgnoreCase("q")) {
				if (object instanceof BusinessObject) {
					((BusinessObject) object).setValueToSearch(sVal);
				}
			}

			Field field = (Field) hash.get(key);
			if (field != null) {
				field.setAccessible(true);
				String fieldType = field.getType().getName();
				if (fieldType.equals("java.util.Date")) {
					Date date = Converter.string2Date(sVal);
					field.set(object, date);
				} else if (fieldType.equals("java.lang.Integer")) {
					Integer integer = Converter.string2Integer(sVal);
					field.set(object, integer);
				} else if (fieldType.equals("java.lang.Float")) {
					Float floatVal = Converter.string2Float(sVal);
					field.set(object, floatVal);
				} else if (fieldType.equals("java.lang.Double")) {
					Double doubleVal = Converter.string2Double(sVal);
					field.set(object, doubleVal);
				} else {
					field.set(object, sVal);
				}
			}
		}

	}

	/**
	 * obtiene los campos de la clase padre.
	 * 
	 * @param object
	 *            objeto del cual se extraen los metodos
	 * @return numero de campos contenidos en el objeto.
	 */
	@SuppressWarnings("unchecked")
	public Field[] getFieldsFromParentClass(Object object) {
		Class _class = object.getClass().getSuperclass();
		Field[] fields = _class.getDeclaredFields();
		return fields;
	}

}
